// src/api/image-comparison.js
// 图片对比服务，基于同事的Python脚本逻辑

import axios from 'axios'
import logger from '../utils/logger.js'

// 图片对比服务类
class ImageComparisonService {
  constructor() {
    this.baseURL = 'https://17a0bdf8.r12.cpolar.top'
    this.timeout = 15000
  }

  // 调用后端图片对比API
  async compareImages(imagePaths) {
    try {
      logger.log('开始图片对比:', imagePaths)
      
      // 创建FormData来上传图片
      const formData = new FormData()
      
      // 添加图片文件到FormData
      for (let i = 0; i < imagePaths.length; i++) {
        const imagePath = imagePaths[i]
        // 如果是本地路径，需要读取文件
        if (typeof imagePath === 'string' && imagePath.startsWith('/')) {
          // 这里需要处理本地文件路径
          // 在实际应用中，可能需要先上传图片到服务器
          formData.append(`image${i}`, imagePath)
        } else {
          formData.append(`image${i}`, imagePath)
        }
      }

      const response = await axios.post(`${this.baseURL}/goc/image/compare`, formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
        timeout: this.timeout
      })

      return response.data.similarity || 0.8
    } catch (error) {
      logger.error('图片对比API调用失败:', error)
      // 如果API不可用，使用模拟数据
      return this.getMockSimilarity(imagePaths)
    }
  }

  // 模拟相似度计算（当API不可用时使用）
  getMockSimilarity(imagePaths) {
    logger.log('使用模拟相似度计算')
    
    // 基于图片路径生成一个伪随机的相似度
    let hash = 0
    for (let i = 0; i < imagePaths.length; i++) {
      for (let j = 0; j < imagePaths[i].length; j++) {
        hash = ((hash << 5) - hash + imagePaths[i].charCodeAt(j)) & 0xffffffff
      }
    }
    
    // 将hash转换为0-1之间的相似度
    const similarity = Math.abs(hash) % 100 / 100
    return Math.max(0.3, Math.min(0.95, similarity)) // 限制在0.3-0.95之间
  }

  // 本地图片对比（使用Canvas API）
  async compareImagesLocal(image1Path, image2Path, mode = 'strict') {
    try {
      logger.log('🔍 开始本地图片对比...')
      logger.log('📸 图片1路径/数据:', image1Path.substring(0, 100))
      logger.log('📸 图片2路径/数据:', image2Path.substring(0, 100))
      
      // 加载图片
      const img1 = await this.loadImage(image1Path)
      const img2 = await this.loadImage(image2Path)
      
      logger.log('✅ 图片加载成功')
      logger.log('📐 图片1尺寸:', img1.width, 'x', img1.height)
      logger.log('📐 图片2尺寸:', img2.width, 'x', img2.height)
      
      // 创建Canvas进行图片对比
      const canvas1 = document.createElement('canvas')
      const canvas2 = document.createElement('canvas')
      const ctx1 = canvas1.getContext('2d')
      const ctx2 = canvas2.getContext('2d')
      
      // 设置Canvas尺寸 - 使用更大的尺寸以保留更多细节
      const size = 128 // 从64增加到128，保留更多细节
      canvas1.width = canvas1.height = size
      canvas2.width = canvas2.height = size
      
      // 填充白色背景（统一背景色）
      ctx1.fillStyle = 'white'
      ctx1.fillRect(0, 0, size, size)
      ctx2.fillStyle = 'white'
      ctx2.fillRect(0, 0, size, size)
      
      // 绘制图片到Canvas
      ctx1.drawImage(img1, 0, 0, size, size)
      ctx2.drawImage(img2, 0, 0, size, size)
      
      // 获取图片数据
      const imageData1 = ctx1.getImageData(0, 0, size, size)
      const imageData2 = ctx2.getImageData(0, 0, size, size)
      
      // 🔥 使用多种对比方法综合评分
      const pixelSimilarity = this.calculatePixelSimilarity(imageData1, imageData2)
      const edgeSimilarity = this.calculateEdgeSimilarity(imageData1, imageData2)
      const structuralSimilarity = this.calculateStructuralSimilarity(imageData1, imageData2)
      
      logger.log('📊 像素相似度:', pixelSimilarity)
      logger.log('📊 边缘相似度:', edgeSimilarity)
      logger.log('📊 结构相似度:', structuralSimilarity)
      
      // 根据模式使用不同的权重
      let finalSimilarity
      if (mode === 'strict') {
        // 严谨模式：像素70% + 边缘30%
        finalSimilarity = pixelSimilarity * 0.70 + edgeSimilarity * 0.30
        logger.log('🎯 最终综合相似度 [严谨模式: 像素70% + 边缘30%]:', finalSimilarity)
      } else {
        // 宽松模式：像素68% + 边缘32%
        finalSimilarity = pixelSimilarity * 0.68 + edgeSimilarity * 0.32
        logger.log('🎯 最终综合相似度 [宽松模式: 像素68% + 边缘32%]:', finalSimilarity)
        
        // 🔥 宽松模式额外条件：边缘相似度必须大于0.0427
        if (edgeSimilarity <= 0.0427) {
          logger.log('❌ 宽松模式判定失败：边缘相似度', edgeSimilarity.toFixed(4), '≤ 0.0427，形状不匹配')
          return 0 // 不满足条件，直接返回0
        }
        logger.log('✅ 宽松模式边缘检查通过：边缘相似度', edgeSimilarity.toFixed(4), '> 0.0427')
      }
      
      return finalSimilarity
    } catch (error) {
      logger.error('❌ 本地图片对比失败:', error)
      logger.error('❌ 错误详情:', error.message || error)
      // 图片加载失败时返回0，确保不会错误通过
      return 0
    }
  }

  // 加载图片（带超时和重试机制）
  loadImage(src, timeout = 10000) {
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.crossOrigin = 'anonymous'
      
      // 设置超时
      const timeoutId = setTimeout(() => {
        img.src = '' // 取消加载
        reject(new Error(`图片加载超时 (${timeout}ms): ${src.substring(0, 100)}`))
      }, timeout)
      
      img.onload = () => {
        clearTimeout(timeoutId)
        logger.log('✅ 图片加载成功:', src.substring(0, 100))
        resolve(img)
      }
      
      img.onerror = (error) => {
        clearTimeout(timeoutId)
        logger.error('❌ 图片加载失败:', src.substring(0, 100))
        logger.error('❌ 可能的原因: CORS跨域问题、网络连接失败、图片不存在')
        reject(new Error(`图片加载失败: ${src.substring(0, 100)}`))
      }
      
      img.src = src
    })
  }

  // 计算两张图片的相似度（只比对图形区域，忽略白色背景）
  calculatePixelSimilarity(imageData1, imageData2) {
    const data1 = imageData1.data
    const data2 = imageData2.data
    let diff = 0
    let graphicPixelCount = 0 // 统计非白色像素数量
    
    for (let i = 0; i < data1.length; i += 4) {
      const r1 = data1[i]
      const g1 = data1[i + 1]
      const b1 = data1[i + 2]
      const r2 = data2[i]
      const g2 = data2[i + 1]
      const b2 = data2[i + 2]
      
      // 判断两张图片中至少有一个像素不是白色（说明这是图形区域）
      const isGraphic1 = r1 < 250 || g1 < 250 || b1 < 250
      const isGraphic2 = r2 < 250 || g2 < 250 || b2 < 250
      
      if (isGraphic1 || isGraphic2) {
        // 只计算图形区域的差异
        const rDiff = Math.abs(r1 - r2)
        const gDiff = Math.abs(g1 - g2)
        const bDiff = Math.abs(b1 - b2)
        
        diff += (rDiff + gDiff + bDiff) / 3
        graphicPixelCount++
      }
    }
    
    // 如果没有图形像素，返回0相似度
    if (graphicPixelCount === 0) {
      logger.log('⚠️ 警告：没有检测到图形内容')
      return 0
    }
    
    // 将差异转换为相似度（0-1）
    const maxDiff = 255 * graphicPixelCount
    const similarity = 1 - (diff / maxDiff)
    
    logger.log('📊 图形像素数量:', graphicPixelCount, '总像素数量:', data1.length / 4, '图形占比:', (graphicPixelCount / (data1.length / 4) * 100).toFixed(2) + '%')
    
    return Math.max(0, Math.min(1, similarity))
  }

  // 🔥 新增：边缘检测相似度对比
  calculateEdgeSimilarity(imageData1, imageData2) {
    // 提取边缘
    const edges1 = this.detectEdges(imageData1)
    const edges2 = this.detectEdges(imageData2)
    
    // 对比边缘（使用更精确的相似度计算）
    let totalDiff = 0
    let totalEdgeStrength = 0
    let edgePixelCount = 0
    
    for (let i = 0; i < edges1.length; i++) {
      const edge1 = edges1[i]
      const edge2 = edges2[i]
      
      // 只考虑至少有一个图片存在边缘的像素
      if (edge1 > 0 || edge2 > 0) {
        const diff = Math.abs(edge1 - edge2)
        const maxEdge = Math.max(edge1, edge2)
        
        totalDiff += diff
        totalEdgeStrength += maxEdge
        edgePixelCount++
      }
    }
    
    // 如果没有边缘，返回高相似度（说明两张图片都没有边缘）
    if (edgePixelCount === 0) {
      return 1.0
    }
    
    // 计算平均相对差异
    const avgDiff = totalDiff / edgePixelCount
    const avgEdgeStrength = totalEdgeStrength / edgePixelCount
    
    // 相似度 = 1 - (平均差异 / 平均边缘强度)
    const similarity = avgEdgeStrength > 0 ? 1 - (avgDiff / avgEdgeStrength) : 1.0
    
    return Math.max(0, Math.min(1, similarity))
  }

  // 🔥 新增：结构相似度对比（分块对比）
  calculateStructuralSimilarity(imageData1, imageData2) {
    const blockSize = 8 // 8x8的块
    const width = Math.sqrt(imageData1.data.length / 4)
    const blocksPerRow = Math.floor(width / blockSize)
    
    let matchingBlocks = 0
    let totalBlocks = 0
    
    for (let by = 0; by < blocksPerRow; by++) {
      for (let bx = 0; bx < blocksPerRow; bx++) {
        const block1Features = this.extractBlockFeatures(imageData1, bx * blockSize, by * blockSize, blockSize)
        const block2Features = this.extractBlockFeatures(imageData2, bx * blockSize, by * blockSize, blockSize)
        
        // 对比块特征
        const blockSimilarity = this.compareBlockFeatures(block1Features, block2Features)
        if (blockSimilarity > 0.7) {
          matchingBlocks++
        }
        totalBlocks++
      }
    }
    
    return totalBlocks > 0 ? matchingBlocks / totalBlocks : 0
  }

  // 简单的Sobel边缘检测
  detectEdges(imageData) {
    const data = imageData.data
    const width = Math.sqrt(data.length / 4)
    const edges = new Array(width * width).fill(0)
    
    for (let y = 1; y < width - 1; y++) {
      for (let x = 1; x < width - 1; x++) {
        const idx = (y * width + x) * 4
        
        // 转换为灰度
        const gray = (data[idx] + data[idx + 1] + data[idx + 2]) / 3
        
        // Sobel算子
        const gx = (
          -1 * this.getGray(data, x - 1, y - 1, width) +
          1 * this.getGray(data, x + 1, y - 1, width) +
          -2 * this.getGray(data, x - 1, y, width) +
          2 * this.getGray(data, x + 1, y, width) +
          -1 * this.getGray(data, x - 1, y + 1, width) +
          1 * this.getGray(data, x + 1, y + 1, width)
        )
        
        const gy = (
          -1 * this.getGray(data, x - 1, y - 1, width) +
          -2 * this.getGray(data, x, y - 1, width) +
          -1 * this.getGray(data, x + 1, y - 1, width) +
          1 * this.getGray(data, x - 1, y + 1, width) +
          2 * this.getGray(data, x, y + 1, width) +
          1 * this.getGray(data, x + 1, y + 1, width)
        )
        
        edges[y * width + x] = Math.sqrt(gx * gx + gy * gy)
      }
    }
    
    return edges
  }

  getGray(data, x, y, width) {
    const idx = (y * width + x) * 4
    return (data[idx] + data[idx + 1] + data[idx + 2]) / 3
  }

  // 提取块特征
  extractBlockFeatures(imageData, startX, startY, blockSize) {
    const data = imageData.data
    const width = Math.sqrt(data.length / 4)
    
    let avgR = 0, avgG = 0, avgB = 0
    let edgePixels = 0
    let totalPixels = 0
    
    for (let y = startY; y < startY + blockSize && y < width; y++) {
      for (let x = startX; x < startX + blockSize && x < width; x++) {
        const idx = (y * width + x) * 4
        avgR += data[idx]
        avgG += data[idx + 1]
        avgB += data[idx + 2]
        
        // 检测是否为边缘像素（非白色）
        if (data[idx] < 250 || data[idx + 1] < 250 || data[idx + 2] < 250) {
          edgePixels++
        }
        
        totalPixels++
      }
    }
    
    return {
      avgColor: {
        r: avgR / totalPixels,
        g: avgG / totalPixels,
        b: avgB / totalPixels
      },
      edgeDensity: edgePixels / totalPixels
    }
  }

  // 对比块特征
  compareBlockFeatures(features1, features2) {
    // 颜色差异
    const colorDiff = (
      Math.abs(features1.avgColor.r - features2.avgColor.r) +
      Math.abs(features1.avgColor.g - features2.avgColor.g) +
      Math.abs(features1.avgColor.b - features2.avgColor.b)
    ) / (3 * 255)
    
    // 边缘密度差异
    const edgeDiff = Math.abs(features1.edgeDensity - features2.edgeDensity)
    
    // 综合相似度
    const similarity = 1 - (colorDiff * 0.3 + edgeDiff * 0.7)
    
    return Math.max(0, Math.min(1, similarity))
  }
}

// 创建单例实例
const imageComparisonService = new ImageComparisonService()

// 导出主要函数
export const compareImages = async (imagePaths) => {
  if (imagePaths.length < 2) {
    throw new Error('至少需要两张图片进行对比')
  }
  
  // 第一张是基准图，后面的都是测试图
  const baseImage = imagePaths[0]
  const testImages = imagePaths.slice(1)
  
  const similarities = []
  
  for (const testImage of testImages) {
    try {
      const similarity = await imageComparisonService.compareImages([baseImage, testImage])
      similarities.push(similarity)
    } catch (error) {
      logger.warn('图片对比失败:', error)
      similarities.push(0.5) // 默认相似度
    }
  }
  
  // 返回平均相似度
  const avgSimilarity = similarities.reduce((sum, sim) => sum + sim, 0) / similarities.length
  return avgSimilarity
}

// 导出服务实例
export default imageComparisonService

